
import java.io.File;
import java.util.Vector;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

//import Transaction.Code;

//import DVD.Status;

public class TestLibrary 
{
	private Library lib;
	
	@Before
	public void setUp() throws Exception 
	{
		lib = new Library();
		lib.loadCollection("tests\\testMaster.in");
	}
	
	@Test
	public void testProcessCreateStandard() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.CREATE, "Sample Created", DVD.Status.RENTAL, 1, 0);
				
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Created", 1, 0, 2, 1);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Created"));
	}
	
	@Test
	public void testProcessCreateUsedNo() throws Exception
	{
		Transaction t;
		t = new Transaction(Transaction.Code.CREATE, "Sample Placeholder", DVD.Status.RENTAL, 1, 0);
		lib.processTransaction(t);

		t = new Transaction(Transaction.Code.CREATE, "Sample Created", DVD.Status.RENTAL, 1, 0);
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Created", 1, 0, 5, 1);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Created"));
	}
	
	@Test 
	public void testProcessCreateAlreadyExists() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.CREATE, "Sample Rental", DVD.Status.SALE, 2, 1);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintFailureException ex)
		{
			MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Rental", 1, 0, 0, 1);			
			Assert.assertEquals(dvd, lib.getDVD("Sample Rental"));
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessRentStandard() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.RENT, "Sample Rental", DVD.Status.RENTAL, 1, 0);
		
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Rental", 0, 0, 0, 1);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Rental"));
	}
	
	@Test
	public void testProcessRentAboveMax() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.RENT, "Sample Rental", DVD.Status.RENTAL, 2, 0);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintFailureException ex)
		{
			MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Rental", 1, 0, 0, 1);			
			Assert.assertEquals(dvd, lib.getDVD("Sample Rental"));
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessRentTitleDoesNotExist() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.RENT, "Sample Does Not Exist", DVD.Status.RENTAL, 1, 0);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessRentWrongStatus() throws Exception
	{
		
		//public MasterDVD(Status status, String title, int quantity, double price, int number, int totalQuantity) 
			//public Transaction (Code code, String title, DVD.Status status, int quantity, double price)

		Transaction t = new Transaction(Transaction.Code.RENT, "Sample Sale", DVD.Status.SALE, 1, 1);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			MasterDVD dvd = new MasterDVD(DVD.Status.SALE, "Sample Sale", 1, 1, 1, 1);			
			Assert.assertEquals(dvd, lib.getDVD("Sample Sale"));
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessReturnStandard() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.RETURN, "Sample Rental", DVD.Status.RENTAL, 1, 0);
		
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Rental", 2, 0, 0, 2);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Rental"));
	}
	
	@Test
	public void testProcessReturnTitleDoesNotExist() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.RETURN, "Sample Create", DVD.Status.RENTAL, 1, 1);
		
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.SALE, "Sample Create", 1, 1, 2, 1);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Create"));
	}
	
	@Test
	public void testProcessReturnUsedNo() throws Exception
	{
		Transaction t;
		t = new Transaction(Transaction.Code.RETURN, "Sample Placeholder", DVD.Status.RENTAL, 1, 1);
		lib.processTransaction(t);

		t = new Transaction(Transaction.Code.RETURN, "Sample Created", DVD.Status.RENTAL, 1, 1);
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.SALE, "Sample Created", 1, 1, 5, 1);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Created"));
	}
	
	@Test
	public void testProcessReturnAboveMax() throws Exception
	{
		
		Transaction t = new Transaction(Transaction.Code.RETURN, "Sample Max Rental", DVD.Status.RENTAL, 1, 0);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessAddStandard() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.ADD, "Sample Rental", DVD.Status.RENTAL, 1, 0);
		
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Rental", 2, 0, 0, 2);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Rental"));
	}
	
	@Test
	public void testProcessAddTitleDoesNotExist() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.ADD, "Sample Does Not Exist", DVD.Status.RENTAL, 1, 0);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessAddAboveMax() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.ADD, "Sample Max Rental", DVD.Status.RENTAL, 1, 0);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Max Rental", 9999, 0, 3, 9999);			
			Assert.assertEquals(dvd, lib.getDVD("Sample Max Rental"));
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessRemoveStandard() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.REMOVE, "Sample Rental", DVD.Status.RENTAL, 0, 0);
		
		lib.processTransaction(t);
		
		boolean exception = false;
		
		try
		{
			lib.getDVD("Sample Rental");
		}
		catch ( TitleConflictException ex )
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessRemoveTitleDoesNotExist() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.REMOVE, "Sample Does Not Exist", DVD.Status.RENTAL, 0, 0);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessBuyStandard() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.BUY, "Sample Sale", DVD.Status.SALE, 1, 1);
		
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.SALE, "Sample Sale", 0, 1, 1, 0);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Sale"));
	}
	
	@Test
	public void testProcessBuyTitleDoesNotExist() throws Exception
	{
		//public MasterDVD(Status status, String title, int quantity, double price, int number, int totalQuantity) 
		//public Transaction (Code code, String title, DVD.Status status, int quantity, double price)

		Transaction t = new Transaction(Transaction.Code.BUY, "Sample Does Not Exist", DVD.Status.SALE, 1, 1);
		
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessBuyAboveQuantity() throws Exception
	{
		//public MasterDVD(Status status, String title, int quantity, double price, int number, int totalQuantity) 
		//public Transaction (Code code, String title, DVD.Status status, int quantity, double price)

		Transaction t = new Transaction(Transaction.Code.BUY, "Sample Sale", DVD.Status.SALE, 2, 1);
		
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintFailureException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessBuyIncorrectStatus() throws Exception
	{
		
		Transaction t = new Transaction(Transaction.Code.BUY, "Sample Rental", DVD.Status.SALE, 1, 0);
		
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testLoadCollectionShortRecord() throws Exception
	{
		Library testLib = new Library();
		
		boolean exception = false;
		
		try
		{
			testLib.loadCollection("tests\\testLoadCollectionArrayIndexOutOfBounds.in");
		}
		catch (FatalErrorException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testLoadCollectionNumberFormat() throws Exception
	{
		//public MasterDVD(Status status, String title, int quantity, double price, int number, int totalQuantity) 
		//public Transaction (Code code, String title, DVD.Status status, int quantity, double price)

		Library testLib = new Library();
		
		boolean exception = false;
		
		try
		{
			testLib.loadCollection("tests\\testLoadCollectionNumberFormat.in");
		}
		catch (FatalErrorException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testProcessSellRental() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.SELL, "Sample Rental", DVD.Status.RENTAL, 0, 1);
		
		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.SALE, "Sample Rental", 1, 1, 0, 1);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Rental"));
	}
	
	@Test
	public void testProcessSellSale() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.SELL, "Sample Sale", DVD.Status.SALE, 0, 0);

		lib.processTransaction(t);
		
		MasterDVD dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Sale", 1, 0, 1, 1);
		
		Assert.assertEquals(dvd, lib.getDVD("Sample Sale"));
	}	
	
	@Test
	public void testProcessSellTitleDoesNotExist() throws Exception
	{
		Transaction t = new Transaction(Transaction.Code.SELL, "Sample Does Not Exist", DVD.Status.RENTAL, 0, 0);
		boolean exception = false;
		
		try
		{
			lib.processTransaction(t);
		}
		catch (ConstraintWarningException ex)
		{
			exception = true;
		}
		
		Assert.assertTrue(exception);
	}
	
	@Test
	public void testGetVector() throws Exception
	{
		Vector<MasterDVD> expected = new Vector<MasterDVD>();
		
		MasterDVD dvd;
		
		dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Rental", 1, 0, 0, 1);
		expected.add(dvd);
		dvd = new MasterDVD(DVD.Status.SALE, "Sample Sale", 1, 1, 1, 1);
		expected.add(dvd);
		dvd = new MasterDVD(DVD.Status.RENTAL, "Sample Max Rental", 9999, 0, 3, 9999);
		expected.add(dvd);
		dvd = new MasterDVD(DVD.Status.SALE, "Sample Max Sale", 9999, 1, 4, 9999);
		expected.add(dvd);
		
		Assert.assertEquals(expected, lib.getVector());
	}
	
	@Test
	public void testCreateCurrentDVDFileStandard() throws Exception
	{
		lib.createCurrentDVDFile("tests\\testCurrent.out");
		
		File out = new File("tests\\testCurrent.out");
		
		Assert.assertTrue(out.exists());
		
		out.delete();		
	}
	
	@Test
	public void testCreateMasterDVDFileStandard() throws Exception
	{
		lib.createMasterDVDFile("tests\\testMaster.out");
		
		File out = new File("tests\\testMaster.out");
		
		Assert.assertTrue(out.exists());
		
		out.delete();
	}
}
